﻿using System;
using System.Collections.Generic;
using LLoger;
using System.Linq;

namespace LimitatorInterfaces.CorrectServices
{
    public class CorrectionLimitService : ServiceBase, ICorrectionLimitService
    {
        private readonly ILimitCorrector _corrector;
        private List<LimitEntity> _sourceLinmits = null;
        private List<CorrectionLimitEntity> _corrections = null;
        private readonly ILoadProvider _loadProvider;
        private readonly ICorrectionParser _parser;

        public CorrectionLimitService(string configPath, ILoadProvider loadProvider, ICorrectionParser parser, ILogWriter logWriter, ILimitCorrector corrector)
            : base(configPath, logWriter)
        {
            if (loadProvider == null) throw new ArgumentNullException("loadProvider");
            if (parser == null) throw new ArgumentNullException("parser");
            if (corrector == null) throw new ArgumentNullException("corrector");

            _loadProvider = loadProvider;
            _corrector = corrector;
            _parser = parser;
        }

        public virtual void LoadSourceLimits(List<LimitEntity> sourceLimits)
        {
            if (sourceLimits == null) throw new ArgumentNullException("sourceLinmits");

            _sourceLinmits = sourceLimits;
        }

        public virtual void CorrectLimits()
        {
            try
            {
                foreach (var correction in _corrections)
                {
                    var lim = _sourceLinmits.Where(
                        e => e.ClientCode == correction.ClientCode
                             //&& e.ActiveCode == correction.ActiveCode
                             && e.IsMoney == correction.IsMoney);

                    int cnt = lim.Count();

                    if (cnt < 1)
                    {
                        LogWriter.WriteLine("Не найден лимит в исходной талице:ClientCode={0} ", correction.ClientCode);
                        continue;
                    }

                    if (cnt > 1)
                        throw new CorrectionServiceException(
                            string.Format(
                                "В исходном наборе имеется больше одного лимита с атрибутами ClientCode={0}, IsMoney={1}",
                                correction.ClientCode, correction.IsMoney));

                    _corrector.Correct(lim.Single(), correction);
                }
            }
            catch (Exception ex)
            {
                LogWriter.WriteLine(ex);
                throw;
            }
        }

        /// <summary>
        /// Загрузка коррекций из источника.
        /// Сервису коррекции необходимо предварительно задать параметр LoadCorrectionsProviderParam; 
        /// в зависимости от реализации может быть строка подключения к БД, путь к файлу и пр...
        /// </summary>
        public void LoadCorrections()
        {
            var param = GetStartWithSettingValues(CorrectionServiceRes.LoadCorrectionsProviderParam);

            var loadedCorr = _loadProvider.LoadFromSource(param);

            if (loadedCorr == null || loadedCorr.Length == 0)
                throw new LoadProviderException("Не удалось загрузить корректирующие данные");

            LogWriter.WriteLine("Всего загружено записей из источника: "+loadedCorr.Length);

            _corrections = new List<CorrectionLimitEntity>();


            foreach (var corr in loadedCorr)
            {
                _corrections.Add(_parser.ParceFrom(corr));
            }

            LogWriter.WriteLine("Всего записей преобразовано в коррекции: " + _corrections.Count);

        }

    }
}